﻿using Cyss.Core;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Cyss.Core.Api.Authorized
{
    /// <summary>
    /// 记录请求日志中间件
    /// </summary>
    public class LoggingMiddleware
    {
        private readonly RequestDelegate _next;

        public LoggingMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Method.ToUpper().Equals("OPTIONS"))
            {
                await _next(context);
            }
            else
            {
                HttpClientMessageModel logModel = new HttpClientMessageModel();
                HttpRequest request = context.Request;
                logModel.Id = Guid.NewGuid().ToString();
                logModel.Url = request.Path.ToString();
                logModel.Headers = string.Join(",", request.Headers.ToDictionary(x => x.Key, v => string.Join(";", v.Value.ToList())));
                logModel.HttpMethod = request.Method;
                logModel.ExecuteStartTime = DateTimeOffset.Now;
                //追踪实别器
                logModel.TraceIdentifier = context.TraceIdentifier;
                // 获取请求body内容
                if (request.Method.ToLower().Equals("post"))
                {
                    request.EnableBuffering();
                    StreamReader sr = new StreamReader(request.Body);
                    var requestBody = await sr.ReadToEndAsync();
                    request.Body.Seek(0, SeekOrigin.Begin);
                    logModel.Content = requestBody;
                }
                else if (request.Method.ToLower().Equals("get"))
                {
                    logModel.Content = request.QueryString.Value;
                }

                var response = context.Response;
                var responseOriginalBody = response.Body;
                var memStream = new MemoryStream();
                response.Body = memStream;

                await _next(context);

                // 获取Response.Body内容
                //处理执行其他中间件后的ResponseBody
                memStream.Position = 0;
                var responseReader = new StreamReader(memStream);
                var responseBody = await responseReader.ReadToEndAsync();

                logModel.ResponseString = responseBody;
                logModel.ExecuteEndTime = DateTimeOffset.Now;
                IOCEngine.Resolve<IRequestLogging>()?.Insert(logModel);
                memStream.Position = 0;
                await memStream.CopyToAsync(responseOriginalBody);
                response.Body = responseOriginalBody;


                //context.Response.OnCompleted(Completed, logModel);

                //// 响应完成记录时间和存入日志
                //context.Response.OnCompleted(() =>
                //{
                //    try
                //    {
                //        var Id = _httpContextAccessor.HttpContext.Items["RequestId"].ToString();
                //        var logModel = concurrentDictionary[Id];
                //        logModel.ExecuteEndTime = DateTimeOffset.Now;
                //        LoggingMiddleware.WriteTextLog(logModel);
                //        concurrentDictionary.TryRemove(Id, out logModel);
                //        return Task.CompletedTask;
                //    }
                //    catch (Exception ex)
                //    {
                //        return Task.FromException(ex);
                //    }
                //});
            }
        }

        //async Task Completed<HttpClientMessageModel>(HttpClientMessageModel para)
        //{
        //    try
        //    {
        //        logModel.ExecuteEndTime = DateTimeOffset.Now;
        //        LoggingMiddleware.WriteTextLog(logModel);
        //        await Task.FromResult(string.Empty);
        //    }
        //    catch (Exception ex)
        //    {
        //        await Task.FromResult(string.Empty);
        //    }
        //}
    }

    /// <summary>
    /// 扩展中间件
    /// </summary>
    public static class LoggingMiddlewareExtensions
    {
        /// <summary>
        /// 开启记录api请求日志的中间件
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseRequestResponseLogging(this IApplicationBuilder app)
        {
            return app.UseMiddleware<LoggingMiddleware>();
        }
    }

}
